{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/hzy/anaconda3/anaconda/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.\n",
      "  \"This module will be removed in 0.20.\", DeprecationWarning)\n"
     ]
    }
   ],
   "source": [
    "from dataset import CaliforniaHousingDataset\n",
    "import numpy as np\n",
    "from collections import defaultdict\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.metrics import r2_score\n",
    "import matplotlib.pyplot as plt\n",
    "import xgboost\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def row2index(row, divide):\n",
    "    '''\n",
    "    逻辑：\n",
    "        0<= x < 0.25 0\n",
    "        0.25<= x < 0.5 1\n",
    "        0.5<= x < 0.75 2\n",
    "        0.75<= x <= 1.0 3（单独处理）\n",
    "    '''\n",
    "    index = []\n",
    "    for i, x in enumerate(row.flat):\n",
    "        if x == 1.0:\n",
    "            index.append(str(divide[i] - 1))\n",
    "        else:\n",
    "            index.append(str(int(x*divide[i])))\n",
    "    return ','.join(index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "dataset = CaliforniaHousingDataset()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## train X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_X = dataset.train_X\n",
    "train_y = dataset.train_y\n",
    "\n",
    "# 0~1之间\n",
    "train_X = (train_X - train_X.min(axis=0)) /  (train_X.max(axis=0) - train_X.min(axis=0))\n",
    "\n",
    "divides = [\n",
    "    [2, 2, 2, 2, 2, 2, 2, 2],\n",
    "    [2, 1, 2, 2, 1, 2, 2, 1],\n",
    "]\n",
    "num_scales = len(divides)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "grided_feature = [defaultdict(list)] * num_scales\n",
    "grided_label = [defaultdict(list)] * num_scales\n",
    "grided_model = [defaultdict(None)] * num_scales"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i_divide, divide in enumerate(divides):\n",
    "    for j, row in enumerate(train_X):\n",
    "        grided_feature[i_divide][row2index(row, divide)].append(row)\n",
    "        grided_label[i_divide][row2index(row, divide)].append(train_y[j])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i_divide, divide in enumerate(divides):\n",
    "    for key in grided_feature[i_divide]:\n",
    "        grid_train_X = np.array(grided_feature[i_divide][key])\n",
    "        grid_train_y = np.array(grided_label[i_divide][key])\n",
    "        model = xgboost.XGBRegressor()\n",
    "        model.fit(grid_train_X, grid_train_y)\n",
    "        grided_model[i_divide][key] = model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "XGBRegressor(base_score=0.5, colsample_bylevel=1, colsample_bytree=1, gamma=0,\n",
       "       learning_rate=0.1, max_delta_step=0, max_depth=3,\n",
       "       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,\n",
       "       objective='reg:linear', reg_alpha=0, reg_lambda=1,\n",
       "       scale_pos_weight=1, seed=0, silent=True, subsample=1)"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "default_model = xgboost.XGBRegressor()\n",
    "default_model.fit(train_X, train_y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "test_X = dataset.test_X\n",
    "test_y = dataset.test_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 不能直接用train_X，因为此时train_X已经改变了\n",
    "test_X = (test_X - dataset.train_X.min(axis=0)) /  (dataset.train_X.max(axis=0) - dataset.train_X.min(axis=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "preds = []\n",
    "labels = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [],
   "source": [
    "use_default = 0\n",
    "for i, row in enumerate(test_X):\n",
    "    label = test_y[i]\n",
    "    pred = None\n",
    "    for i_divide, divide in enumerate(divides):\n",
    "        key = row2index(row, divide=divide)\n",
    "        if key in grided_model[i_divide]:\n",
    "            pred = grided_model[i_divide][key].predict(row.reshape(1, -1))\n",
    "            break\n",
    "    if pred is None:\n",
    "        # use default model\n",
    "        pred = default_model.predict(row.reshape(1, -1))\n",
    "        use_default += 1\n",
    "    else:\n",
    "        labels.append(label)\n",
    "        preds.append(pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.822534538021\n"
     ]
    }
   ],
   "source": [
    "print(r2_score(labels, preds))\n",
    "# plt.plot(preds, labels, '.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## standard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_X = dataset.train_X\n",
    "train_y = dataset.train_y\n",
    "train_X = (train_X - dataset.train_X.min(axis=0)) /  (dataset.train_X.max(axis=0) - dataset.train_X.min(axis=0))\n",
    "test_X = dataset.test_X\n",
    "test_X = (test_X - dataset.train_X.min(axis=0)) /  (dataset.train_X.max(axis=0) - dataset.train_X.min(axis=0))\n",
    "test_y = dataset.test_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.79386057272999944"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = xgboost.XGBRegressor()\n",
    "model.fit(train_X, train_y)\n",
    "preds = model.predict(test_X)\n",
    "\n",
    "r2_score(test_y, preds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
